// 未来之窗渲染引擎整合到$cq库
// @Name： 未来之窗渲染引擎
// @Author：cybersnow
// @Site： www.ynwlzc.cn
// @LastEdit: 未来之窗
// 2022-10-17

// 渲染引擎全局配置（可外部修改）
$cq.renderConfig = {
    open: "{cwpdapp{",
    close: "}}"
};

// 渲染引擎工具函数
var renderUtils = {
    exp: function(a) {
        return new RegExp(a, "g");
    },
    query: function(a, c, e) {
        var f = ["#([\\s\\S])+?", "([^{#}])*?"][a || 0];
        return this.exp((c || "") + $cq.renderConfig.open + f + $cq.renderConfig.close + (e || ""));
    },
    escape: function(a) {
        return String(a || "").replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/'/g, "&#39;")
            .replace(/"/g, "&quot;");
    },
    error: function(a, b) {
        var c = "未来之窗渲染引擎 Error：";
        if (typeof console !== "undefined" && console.error) {
            console.error(c + a + "\n" + (b || ""));
        }
        return c + a;
    }
};

// 渲染器构造函数
function RenderEngine(tpl) {
    this.tpl = tpl;
    this.cache = null;
}

// 解析模板并生成渲染函数
RenderEngine.prototype.parse = function(data) {
    var tpl = this.tpl;
    var openTag = renderUtils.exp("^" + $cq.renderConfig.open + "#", "");
    var closeTag = renderUtils.exp($cq.renderConfig.close + "$", "");

    // 处理模板字符串，转换为可执行代码
    var code = tpl.replace(/[\r\t\n]/g, " ")
        .replace(renderUtils.exp($cq.renderConfig.open + "#"), $cq.renderConfig.open + "# ")
        .replace(renderUtils.exp($cq.renderConfig.close + "}"), "} " + $cq.renderConfig.close)
        .replace(/\\/g, "\\\\")
        .replace(/(?="|')/g, "\\")
        .replace(renderUtils.query(), function(match) {
            match = match.replace(openTag, "").replace(closeTag, "");
            return '";' + match.replace(/\\/g, "") + '; view+="'";
        })
        .replace(renderUtils.query(1), function(match) {
            var prefix = '"+(';
            match = match.replace(renderUtils.exp($cq.renderConfig.open + "|" + $cq.renderConfig.close), "");
            
            // 处理=开头的变量输出（自动转义）
            if (/^=/.test(match)) {
                match = match.replace(/^=/, "");
                prefix = '"+renderUtils.escape(';
            }
            return prefix + match.replace(/\\/g, "") + ')+"';
        });

    // 包装为可执行函数
    code = '"use strict";var view = "' + code + '";return view;';

    try {
        this.cache = new Function("d", "renderUtils", code);
        return this.cache(data, renderUtils);
    } catch (e) {
        delete this.cache;
        return renderUtils.error(e, tpl);
    }
};

// 执行渲染
RenderEngine.prototype.render = function(data, callback) {
    if (!data) {
        return renderUtils.error("没有提供渲染数据");
    }

    var result = this.cache ? this.cache(data, renderUtils) : this.parse(data);

    if (callback && typeof callback === "function") {
        callback(result);
        return;
    }

    return result;
};

// 为$cq添加render方法（通过模板字符串创建渲染器）
$cq.render = function(tpl) {
    if (typeof tpl !== "string") {
        return renderUtils.error("模板必须是字符串类型");
    }
    return new RenderEngine(tpl);
};

// 为$cq原型添加render方法（通过选择器获取模板渲染）
cyberwin_query.prototype.render = function(data, callback) {
    if (this.elements.length === 0) {
        return renderUtils.error("没有找到匹配的模板元素");
    }

    // 获取第一个匹配元素的innerHTML作为模板
    var tpl = this.elements[0].innerHTML;
    return $cq.render(tpl).render(data, callback);
};
